{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/tomasonjo/blogs/blob/master/lotr_graph_data_science_catalog/Native%20Graph%20Catalog%20feature%20on%20a%20Lord%20of%20the%20Rings%20dataset.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "* Updated to GDS 2.0 version\n",
        "* Link to original blog post: https://towardsdatascience.com/exploring-the-graph-catalog-feature-of-neo4j-graph-data-science-plugin-on-a-lord-of-the-rings-d2de0d0a023"
      ],
      "metadata": {
        "id": "RC_yGh2C0vmq"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!pip install neo4j"
      ],
      "metadata": {
        "id": "z-fimZAx06rg",
        "outputId": "8d363ad7-a12f-4b59-fffd-354d7fbcffd2",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Collecting neo4j\n",
            "  Downloading neo4j-4.4.2.tar.gz (89 kB)\n",
            "\u001b[?25l\r\u001b[K     |███▋                            | 10 kB 18.0 MB/s eta 0:00:01\r\u001b[K     |███████▎                        | 20 kB 12.0 MB/s eta 0:00:01\r\u001b[K     |███████████                     | 30 kB 8.9 MB/s eta 0:00:01\r\u001b[K     |██████████████▋                 | 40 kB 4.4 MB/s eta 0:00:01\r\u001b[K     |██████████████████▎             | 51 kB 4.4 MB/s eta 0:00:01\r\u001b[K     |██████████████████████          | 61 kB 5.2 MB/s eta 0:00:01\r\u001b[K     |█████████████████████████▋      | 71 kB 5.7 MB/s eta 0:00:01\r\u001b[K     |█████████████████████████████▎  | 81 kB 5.4 MB/s eta 0:00:01\r\u001b[K     |████████████████████████████████| 89 kB 3.5 MB/s \n",
            "\u001b[?25hRequirement already satisfied: pytz in /usr/local/lib/python3.7/dist-packages (from neo4j) (2018.9)\n",
            "Building wheels for collected packages: neo4j\n",
            "  Building wheel for neo4j (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Created wheel for neo4j: filename=neo4j-4.4.2-py3-none-any.whl size=115365 sha256=7223bc0578864f59d966b348b03933c4a4ec8ff2f8db26a1651d3bc33ebe1dce\n",
            "  Stored in directory: /root/.cache/pip/wheels/10/d6/28/95029d7f69690dbc3b93e4933197357987de34fbd44b50a0e4\n",
            "Successfully built neo4j\n",
            "Installing collected packages: neo4j\n",
            "Successfully installed neo4j-4.4.2\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "49DZMAFk0tNi"
      },
      "outputs": [],
      "source": [
        "# Define Neo4j connections\n",
        "from neo4j import GraphDatabase\n",
        "host = 'bolt://3.235.2.228:7687'\n",
        "user = 'neo4j'\n",
        "password = 'seats-drunks-carbon'\n",
        "driver = GraphDatabase.driver(host,auth=(user, password))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "D_YiHl-90tNm"
      },
      "outputs": [],
      "source": [
        "# Import libraries\n",
        "import pandas as pd\n",
        "\n",
        "def read_query(query):\n",
        "    with driver.session() as session:\n",
        "        result = session.run(query)\n",
        "        return pd.DataFrame([r.values() for r in result], columns=result.keys())\n",
        "    \n",
        "def run_query(query):\n",
        "    with driver.session() as session:\n",
        "        session.run(query)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "T9yASE5t0tNm"
      },
      "source": [
        "## Import\n",
        "\n",
        "I have used the GoT dataset more times than I can remember, so I decided to explore the internet and search for new exciting graphs. I stumbled upon this Lord of the Rings dataset made available by José Calvo that we will use in this blog post.\n",
        "\n",
        "The dataset describes interactions between persons, places, groups, and things (The Ring). When choosing how to model this dataset, I decided to have \"main\" nodes with two labels, primary label \"Node\" and secondary label one of the following:\n",
        "\n",
        "* Person\n",
        "* Place\n",
        "* Group\n",
        "* Thing"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "id": "uQEM8Xcq0tNp"
      },
      "outputs": [],
      "source": [
        "# Import nodes\n",
        "import_nodes_query = \"\"\"\n",
        "\n",
        "LOAD CSV WITH HEADERS FROM \n",
        "\"https://raw.githubusercontent.com/morethanbooks/projects/master/LotR/ontologies/ontology.csv\" as row \n",
        "FIELDTERMINATOR \"\\t\" \n",
        "WITH row, CASE row.type WHEN 'per' THEN 'Person' \n",
        "                        WHEN 'gro' THEN 'Group' \n",
        "                        WHEN 'thin'THEN 'Thing' \n",
        "                        WHEN 'pla' THEN 'Place' \n",
        "                        END as label \n",
        "CALL apoc.create.nodes(['Node',label], [apoc.map.clean(row,['type','subtype'],[null,\"\"])]) YIELD node \n",
        "WITH node, row.subtype as class \n",
        "MERGE (c:Class{id:class}) \n",
        "MERGE (node)-[:PART_OF]->(c)\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "run_query(import_nodes_query)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "id": "6jt1bAgM0tNq"
      },
      "outputs": [],
      "source": [
        "# Import relationships\n",
        "import_relationships_query = \"\"\"\n",
        "\n",
        "UNWIND ['1','2','3'] as book \n",
        "LOAD CSV WITH HEADERS FROM \n",
        "\"https://raw.githubusercontent.com/morethanbooks/projects/master/LotR/tables/networks-id-volume\" + book + \".csv\" AS row \n",
        "MATCH (source:Node{id:coalesce(row.IdSource,row.Source)})\n",
        "MATCH (target:Node{id:coalesce(row.IdTarget,row.Target)})\n",
        "CALL apoc.create.relationship(source, \"INTERACTS_\" + book, \n",
        "     {weight:toInteger(row.Weight)}, target) YIELD rel\n",
        "RETURN distinct true\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "run_query(import_relationships_query)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KYDmbkxJ0tNr"
      },
      "source": [
        "## Graph data science\n",
        "\n",
        "The syntax for creating named graphs in Graph Catalog is:\n",
        "\n",
        "\n",
        "<code>CALL gds.graph.project(graph name, node label, relationship type).</code>\n",
        "\n",
        "\n",
        "Describing nodes we want to project\n",
        "\n",
        "In general, with the native projection variant, there are three options to describe the nodes we want to project into memory:\n",
        "\n",
        "* Project a single node label using a string:\n",
        "    * 'Label' ('*' is a wildcard operator that projects all nodes)\n",
        "* Project multiple node labels using an array:\n",
        "    * ['Label1', 'Label2', 'Label3']\n",
        "* Project multiple node labels with their properties using a configuration map:\n",
        "    * <pre>{\n",
        "  Label: {\n",
        "    label: \"Label\",\n",
        "    properties: [\n",
        "      \"property1\",\n",
        "      \"property2\"\n",
        "    ]\n",
        "  },\n",
        "  Label2: {\n",
        "    label: \"Label2\",\n",
        "    properties: [\n",
        "      \"foo\",\n",
        "      \"bar\"\n",
        "    ]\n",
        "  }\n",
        "}</pre>\n",
        "\n",
        "An important thing to note regarding projecting node labels:\n",
        "\n",
        ">In the in-memory graph, all projected node labels are merged into a single label. Unlike for relationship >projections, it is currently not possible to specify a filter on projected labels. If the graph is used as input >for an algorithm, all nodes will be considered.\n",
        "\n",
        "While we can filter which node labels we want to project to the in-memory graph, additional filtering of nodes when executing graph algorithm is currently not supported.\n",
        "\n",
        "\n",
        "\n",
        "\n",
        "Describing relationships we want to project\n",
        "\n",
        "The syntax to describe the relationships we want to project is very similar to that of the nodes. \n",
        "\n",
        "* Project a single relationship type using a string:\n",
        "    * 'TYPE' ('*' is a wildcard that projects all relationship-types)\n",
        "* Project multiple relationship types using an array:\n",
        "    * ['TYPE1','TYPE2']\n",
        "* Project more relationship types with their properties using a configuration map:\n",
        "    * <pre>{ALIAS_OF_TYPE: {type:'RELATIONSHIP_TYPE', \n",
        "                 orientation: 'NATURAL',\n",
        "                 aggregation: 'DEFAULT'\n",
        "                 properties:[property1,property2]}</pre>\n",
        "\n",
        "The orientation parameter in the configuration map defines the direction of the relationships we want to project. Possible values are:\n",
        "\n",
        "* 'NATURAL' -> each relationship is projected the same way as it is stored in Neo4j\n",
        "* 'REVERSE' -> each relationship is reversed during graph projection\n",
        "* 'UNDIRECTED' -> each relationship is projected in both natural and reverse orientation\n",
        "\n",
        "An important thing to note is that the GDS library supports running graph algorithms on a multigraph. The aggregation parameter is handy when we want to convert a multigraph to a single graph(not a multigraph), but we'll take a closer look at that in another blog post."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "id": "duAqXRLm0tNs"
      },
      "outputs": [],
      "source": [
        "def drop_graph(name):\n",
        "    with driver.session() as session:\n",
        "        drop_graph_query = \"\"\"\n",
        "        CALL gds.graph.drop('{}');\n",
        "        \"\"\".format(name)\n",
        "        session.run(drop_graph_query)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "aUGjN8p60tNt"
      },
      "source": [
        "### Whole graph projection\n",
        "\n",
        "Let's start by projecting the entire graph into memory using the wildcard operator for both the nodes and the relationships."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "id": "uLHDTtFD0tNu"
      },
      "outputs": [],
      "source": [
        "whole_graph = \"CALL gds.graph.project('whole_graph','*', '*')\"\n",
        "run_query(whole_graph);"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "twv4FFL20tNu"
      },
      "source": [
        "Most of the time, we start the graph analysis by running the (weakly) connected components algorithm to get an idea of how (dis)connected our graph really is. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "id": "Q_X6oIWg0tNv",
        "outputId": "f3202ec1-2e5c-4496-c37b-a35a4432c04b",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 81
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "   componentId  size\n",
              "0            0    86"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-4f76e91a-de7b-4c1e-b34b-b8f7742d1da2\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>componentId</th>\n",
              "      <th>size</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>0</td>\n",
              "      <td>86</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-4f76e91a-de7b-4c1e-b34b-b8f7742d1da2')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-4f76e91a-de7b-4c1e-b34b-b8f7742d1da2 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-4f76e91a-de7b-4c1e-b34b-b8f7742d1da2');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 15
        }
      ],
      "source": [
        "wcc_whole = \"\"\"\n",
        "\n",
        "CALL gds.wcc.stream('whole_graph') YIELD nodeId, componentId \n",
        "RETURN componentId, count(*) as size \n",
        "ORDER BY size DESC LIMIT 10\n",
        "\n",
        "\"\"\"\n",
        "read_query(wcc_whole)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "umtPppCL0tNw"
      },
      "source": [
        "The graph as a whole consists of a single component. Usually, what you'll get with real-world data is a single super component (85+% of all nodes) and a few small disconnected components."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {
        "id": "L3difbDf0tNw"
      },
      "outputs": [],
      "source": [
        "# Drop whole graph\n",
        "drop_graph('whole_graph')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-atE77c70tNw"
      },
      "source": [
        "### Interactions graph\n",
        "\n",
        "In the next step, we want to ignore PART_OF relationships and only focus on INTERACTS_X relationships. We will use an array for describing relationship-types to take into account all three INTERACTS_X relationships."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {
        "id": "8ZqmYNJt0tNw"
      },
      "outputs": [],
      "source": [
        "interacts_query = \"\"\"\n",
        "CALL gds.graph.project('all_interacts','Node', ['INTERACTS_1', 'INTERACTS_2', 'INTERACTS_3'])\n",
        "\"\"\"\n",
        "run_query(interacts_query)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vbpbZqxN0tNx"
      },
      "source": [
        "Let's run the weakly connected components algorithm on our new projected graph. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "id": "fg9cASIE0tNx",
        "outputId": "b80a8613-12d4-45a5-9da0-fde4ca636142",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 143
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "   componentId  size                                                ids\n",
              "0            0    73  [Anduin, Aragorn, Arathorn, Arwen, Bag End, Ba...\n",
              "1           25     1                                       [Old Forest]\n",
              "2           26     1                                         [Mirkwood]"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-f35b7247-bb25-4c4f-a855-7ebd19325d31\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>componentId</th>\n",
              "      <th>size</th>\n",
              "      <th>ids</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>0</td>\n",
              "      <td>73</td>\n",
              "      <td>[Anduin, Aragorn, Arathorn, Arwen, Bag End, Ba...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>25</td>\n",
              "      <td>1</td>\n",
              "      <td>[Old Forest]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>26</td>\n",
              "      <td>1</td>\n",
              "      <td>[Mirkwood]</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-f35b7247-bb25-4c4f-a855-7ebd19325d31')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-f35b7247-bb25-4c4f-a855-7ebd19325d31 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-f35b7247-bb25-4c4f-a855-7ebd19325d31');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 18
        }
      ],
      "source": [
        "wcc_interacts = \"\"\"\n",
        "\n",
        "CALL gds.wcc.stream('all_interacts') YIELD nodeId, componentId \n",
        "RETURN componentId, count(*) as size, collect(gds.util.asNode(nodeId).Label) as ids \n",
        "ORDER BY size DESC LIMIT 10\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "read_query(wcc_interacts)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y0hTb3e-0tNx"
      },
      "source": [
        "Our new graph consists of three components. We have a single super component and two tiny components consisting of only a single node. We can deduce that locations \"Mirkwood\" and \"Old Forest\" have no INTERACTS_X relationships.\n",
        "\n",
        "Let's use the same projected graph and only look at interactions from the first book. We can filter which relationship-types should the graph algorithm consider with the relationshipTypes parameter."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "id": "Rnu3H6RW0tNy",
        "outputId": "9034410e-e849-49b9-a8fd-ee69322eb1b8",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 363
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "   componentId  size                                                ids\n",
              "0            0    62  [Anduin, Aragorn, Arathorn, Arwen, Bag End, Ba...\n",
              "1           21     1                                             [Ents]\n",
              "2           26     1                                         [Mirkwood]\n",
              "3           23     1                                             [Eorl]\n",
              "4           24     1                                            [Éowyn]\n",
              "5           25     1                                       [Old Forest]\n",
              "6           22     1                                            [Éomer]\n",
              "7           27     1                                          [Faramir]\n",
              "8           38     1                                           [Gorbag]\n",
              "9            6     1                                         [Beregond]"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-6482f33f-0e7d-48a0-889b-c3f69375578c\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>componentId</th>\n",
              "      <th>size</th>\n",
              "      <th>ids</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>0</td>\n",
              "      <td>62</td>\n",
              "      <td>[Anduin, Aragorn, Arathorn, Arwen, Bag End, Ba...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>21</td>\n",
              "      <td>1</td>\n",
              "      <td>[Ents]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>26</td>\n",
              "      <td>1</td>\n",
              "      <td>[Mirkwood]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>23</td>\n",
              "      <td>1</td>\n",
              "      <td>[Eorl]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>24</td>\n",
              "      <td>1</td>\n",
              "      <td>[Éowyn]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>5</th>\n",
              "      <td>25</td>\n",
              "      <td>1</td>\n",
              "      <td>[Old Forest]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>6</th>\n",
              "      <td>22</td>\n",
              "      <td>1</td>\n",
              "      <td>[Éomer]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>7</th>\n",
              "      <td>27</td>\n",
              "      <td>1</td>\n",
              "      <td>[Faramir]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>8</th>\n",
              "      <td>38</td>\n",
              "      <td>1</td>\n",
              "      <td>[Gorbag]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>9</th>\n",
              "      <td>6</td>\n",
              "      <td>1</td>\n",
              "      <td>[Beregond]</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-6482f33f-0e7d-48a0-889b-c3f69375578c')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-6482f33f-0e7d-48a0-889b-c3f69375578c button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-6482f33f-0e7d-48a0-889b-c3f69375578c');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 19
        }
      ],
      "source": [
        "wcc_interacts_first_book = \"\"\"\n",
        "\n",
        "CALL gds.wcc.stream('all_interacts', \n",
        "    {relationshipTypes:['INTERACTS_1']}) YIELD nodeId, componentId\n",
        "RETURN componentId, count(*) as size, \n",
        "       collect(gds.util.asNode(nodeId).Label) as ids\n",
        "ORDER BY size DESC LIMIT 10\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "read_query(wcc_interacts_first_book)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gQn6Kni00tNy"
      },
      "source": [
        "We get more disconnected components if we take into account only interactions from the first book. This makes sense as some of the characters/locations haven't yet been introduced in the first book, so they have no INTERACTS_1 relationships."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "id": "jjyDuKbA0tNy"
      },
      "outputs": [],
      "source": [
        "drop_graph('all_interacts')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qKAgU8jl0tNy"
      },
      "source": [
        "### Undirected weighted graph\n",
        "\n",
        "In the last example, we will show how to project an undirected weighted graph. We will consider only nodes labeled Person and Thing, and for relationships, we will project all the INTERACTS_X relationships along with their weight property, which will be treated as undirected."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "metadata": {
        "id": "r5JqAlX00tNz"
      },
      "outputs": [],
      "source": [
        "load_graph = \"\"\"\n",
        "\n",
        "CALL gds.graph.project('undirected_weighted',['Person', 'Thing'], \n",
        "    {INTERACTS_1:{type: 'INTERACTS_1', \n",
        "                  orientation: 'UNDIRECTED', \n",
        "                  properties:['weight']},\n",
        "     INTERACTS_2:{type:'INTERACTS_2',\n",
        "                  orientation: 'UNDIRECTED',\n",
        "                  properties:['weight']},\n",
        "     INTERACTS_3: {type:'INTERACTS_3', \n",
        "                   orientation:'UNDIRECTED',\n",
        "                   properties:['weight']}});\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "run_query(load_graph)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ltQVll6z0tNz"
      },
      "source": [
        "#### Unweighted pagerank\n",
        "\n",
        "To run the unweighted pageRank on our projected graph, we don't have to specify any additional configuration."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "id": "MuO8IQzV0tNz",
        "outputId": "bf5148a1-4ab0-4b89-db66-c747366bb292",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "      name     score\n",
              "0  Aragorn  2.243211\n",
              "1  Gandalf  2.200864\n",
              "2    Frodo  2.099686\n",
              "3      Sam  1.794910\n",
              "4    Gimli  1.636080"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-581be24c-1360-41ab-b0d9-561a0991acc6\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>name</th>\n",
              "      <th>score</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>Aragorn</td>\n",
              "      <td>2.243211</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>Gandalf</td>\n",
              "      <td>2.200864</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>Frodo</td>\n",
              "      <td>2.099686</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>Sam</td>\n",
              "      <td>1.794910</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>Gimli</td>\n",
              "      <td>1.636080</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-581be24c-1360-41ab-b0d9-561a0991acc6')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-581be24c-1360-41ab-b0d9-561a0991acc6 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-581be24c-1360-41ab-b0d9-561a0991acc6');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 22
        }
      ],
      "source": [
        "unweighted_pagerank = \"\"\"\n",
        "\n",
        "CALL gds.pageRank.stream('undirected_weighted')\n",
        "YIELD nodeId, score\n",
        "RETURN gds.util.asNode(nodeId).Label as name, score \n",
        "ORDER BY score DESC LIMIT 5\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "read_query(unweighted_pagerank)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QmE5yAA70tNz"
      },
      "source": [
        "#### Weighted pagerank\n",
        "To let know the algorithm that it should take relationship weights into account, we need to use relationshipWeightProperty parameter."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {
        "id": "-Rtxlayt0tNz",
        "outputId": "c2a82a6c-6f60-4e68-fb58-f31e7d8ba56e",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "      name     score\n",
              "0    Frodo  5.065515\n",
              "1  Gandalf  3.732230\n",
              "2      Sam  3.445908\n",
              "3  Aragorn  3.224506\n",
              "4   Pippin  2.338957"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-4183e85a-3d97-48ed-8c6d-a781240b42fb\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>name</th>\n",
              "      <th>score</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>Frodo</td>\n",
              "      <td>5.065515</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>Gandalf</td>\n",
              "      <td>3.732230</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>Sam</td>\n",
              "      <td>3.445908</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>Aragorn</td>\n",
              "      <td>3.224506</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>Pippin</td>\n",
              "      <td>2.338957</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-4183e85a-3d97-48ed-8c6d-a781240b42fb')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-4183e85a-3d97-48ed-8c6d-a781240b42fb button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-4183e85a-3d97-48ed-8c6d-a781240b42fb');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 23
        }
      ],
      "source": [
        "weigted_pagerank = \"\"\"\n",
        "\n",
        "CALL gds.pageRank.stream('undirected_weighted', {relationshipWeightProperty:'weight'}) \n",
        "YIELD nodeId, score \n",
        "RETURN gds.util.asNode(nodeId).Label as name, score \n",
        "ORDER BY score DESC LIMIT 5\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "read_query(weigted_pagerank)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "v6U6q5IH0tN0"
      },
      "source": [
        "As Frodo has more interactions (defined as weight) with other characters, he comes out on top with the weighted variant of the pageRank."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FZpAeSfc0tN0"
      },
      "source": [
        "### First book analysis\n",
        "\n",
        "To finish this blog post, we will analyze the network of the first book. We start by running the weighted pageRank on the interaction relationships from the first book only."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {
        "id": "srPFySeB0tN0",
        "outputId": "014eec79-5b24-4f9b-ebf1-b5aa704d8ccb",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "      name     score\n",
              "0    Frodo  5.478835\n",
              "1  Gandalf  2.834502\n",
              "2  Aragorn  2.783486\n",
              "3      Sam  2.632037\n",
              "4     Ring  1.964534"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-406977dd-a34f-4bd0-b30e-e90fde987757\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>name</th>\n",
              "      <th>score</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>Frodo</td>\n",
              "      <td>5.478835</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>Gandalf</td>\n",
              "      <td>2.834502</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>Aragorn</td>\n",
              "      <td>2.783486</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>Sam</td>\n",
              "      <td>2.632037</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>Ring</td>\n",
              "      <td>1.964534</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-406977dd-a34f-4bd0-b30e-e90fde987757')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-406977dd-a34f-4bd0-b30e-e90fde987757 button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-406977dd-a34f-4bd0-b30e-e90fde987757');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 24
        }
      ],
      "source": [
        "first_pagerank = \"\"\"\n",
        "\n",
        "CALL gds.pageRank.stream('undirected_weighted', \n",
        "     {relationshipWeightProperty:'weight', relationshipTypes:['INTERACTS_1']}) \n",
        "YIELD nodeId, score \n",
        "RETURN gds.util.asNode(nodeId).Label as name, score \n",
        "ORDER BY score DESC LIMIT 5\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "read_query(first_pagerank)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {
        "id": "4xVhgD6w0tN0",
        "outputId": "18c1c3f5-af9c-4f86-c0cc-1e66648b86f7",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        }
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "   communityId                                            members\n",
              "0           36  [Aragorn, Arathorn, Arwen, Boromir, Denethor, ...\n",
              "1           18  [Balin, Celeborn, Durin, Galadriel, Gimli, Gló...\n",
              "2           34  [Bilbo, Bill, Frodo, Gandalf, Gildor, Merry, P...\n",
              "3           42                              [Goldberry, Bombadil]\n",
              "4            4                                         [Beregond]"
            ],
            "text/html": [
              "\n",
              "  <div id=\"df-08b83cc1-606d-4726-950b-752bbc3a7f2b\">\n",
              "    <div class=\"colab-df-container\">\n",
              "      <div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>communityId</th>\n",
              "      <th>members</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>36</td>\n",
              "      <td>[Aragorn, Arathorn, Arwen, Boromir, Denethor, ...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>18</td>\n",
              "      <td>[Balin, Celeborn, Durin, Galadriel, Gimli, Gló...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>34</td>\n",
              "      <td>[Bilbo, Bill, Frodo, Gandalf, Gildor, Merry, P...</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>42</td>\n",
              "      <td>[Goldberry, Bombadil]</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>4</td>\n",
              "      <td>[Beregond]</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>\n",
              "      <button class=\"colab-df-convert\" onclick=\"convertToInteractive('df-08b83cc1-606d-4726-950b-752bbc3a7f2b')\"\n",
              "              title=\"Convert this dataframe to an interactive table.\"\n",
              "              style=\"display:none;\">\n",
              "        \n",
              "  <svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\"viewBox=\"0 0 24 24\"\n",
              "       width=\"24px\">\n",
              "    <path d=\"M0 0h24v24H0V0z\" fill=\"none\"/>\n",
              "    <path d=\"M18.56 5.44l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94zm-11 1L8.5 8.5l.94-2.06 2.06-.94-2.06-.94L8.5 2.5l-.94 2.06-2.06.94zm10 10l.94 2.06.94-2.06 2.06-.94-2.06-.94-.94-2.06-.94 2.06-2.06.94z\"/><path d=\"M17.41 7.96l-1.37-1.37c-.4-.4-.92-.59-1.43-.59-.52 0-1.04.2-1.43.59L10.3 9.45l-7.72 7.72c-.78.78-.78 2.05 0 2.83L4 21.41c.39.39.9.59 1.41.59.51 0 1.02-.2 1.41-.59l7.78-7.78 2.81-2.81c.8-.78.8-2.07 0-2.86zM5.41 20L4 18.59l7.72-7.72 1.47 1.35L5.41 20z\"/>\n",
              "  </svg>\n",
              "      </button>\n",
              "      \n",
              "  <style>\n",
              "    .colab-df-container {\n",
              "      display:flex;\n",
              "      flex-wrap:wrap;\n",
              "      gap: 12px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert {\n",
              "      background-color: #E8F0FE;\n",
              "      border: none;\n",
              "      border-radius: 50%;\n",
              "      cursor: pointer;\n",
              "      display: none;\n",
              "      fill: #1967D2;\n",
              "      height: 32px;\n",
              "      padding: 0 0 0 0;\n",
              "      width: 32px;\n",
              "    }\n",
              "\n",
              "    .colab-df-convert:hover {\n",
              "      background-color: #E2EBFA;\n",
              "      box-shadow: 0px 1px 2px rgba(60, 64, 67, 0.3), 0px 1px 3px 1px rgba(60, 64, 67, 0.15);\n",
              "      fill: #174EA6;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert {\n",
              "      background-color: #3B4455;\n",
              "      fill: #D2E3FC;\n",
              "    }\n",
              "\n",
              "    [theme=dark] .colab-df-convert:hover {\n",
              "      background-color: #434B5C;\n",
              "      box-shadow: 0px 1px 3px 1px rgba(0, 0, 0, 0.15);\n",
              "      filter: drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.3));\n",
              "      fill: #FFFFFF;\n",
              "    }\n",
              "  </style>\n",
              "\n",
              "      <script>\n",
              "        const buttonEl =\n",
              "          document.querySelector('#df-08b83cc1-606d-4726-950b-752bbc3a7f2b button.colab-df-convert');\n",
              "        buttonEl.style.display =\n",
              "          google.colab.kernel.accessAllowed ? 'block' : 'none';\n",
              "\n",
              "        async function convertToInteractive(key) {\n",
              "          const element = document.querySelector('#df-08b83cc1-606d-4726-950b-752bbc3a7f2b');\n",
              "          const dataTable =\n",
              "            await google.colab.kernel.invokeFunction('convertToInteractive',\n",
              "                                                     [key], {});\n",
              "          if (!dataTable) return;\n",
              "\n",
              "          const docLinkHtml = 'Like what you see? Visit the ' +\n",
              "            '<a target=\"_blank\" href=https://colab.research.google.com/notebooks/data_table.ipynb>data table notebook</a>'\n",
              "            + ' to learn more about interactive tables.';\n",
              "          element.innerHTML = '';\n",
              "          dataTable['output_type'] = 'display_data';\n",
              "          await google.colab.output.renderOutput(dataTable, element);\n",
              "          const docLink = document.createElement('div');\n",
              "          docLink.innerHTML = docLinkHtml;\n",
              "          element.appendChild(docLink);\n",
              "        }\n",
              "      </script>\n",
              "    </div>\n",
              "  </div>\n",
              "  "
            ]
          },
          "metadata": {},
          "execution_count": 26
        }
      ],
      "source": [
        "l_f = \"\"\"\n",
        "\n",
        "CALL gds.louvain.stream('undirected_weighted', \n",
        "    {relationshipWeightProperty:'weight', relationshipTypes:['INTERACTS_1']})\n",
        "YIELD nodeId, communityId\n",
        "RETURN communityId, collect(gds.util.asNode(nodeId).Label) as members\n",
        "ORDER BY size(members) DESC LIMIT 5\n",
        "\n",
        "\"\"\"\n",
        "\n",
        "read_query(l_f)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {
        "id": "7W4BJiaI0tN1"
      },
      "outputs": [],
      "source": [
        "drop_graph('undirected_weighted')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XOQMEZ8Z0tN1"
      },
      "outputs": [],
      "source": [
        ""
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.5.2"
    },
    "colab": {
      "name": "Native Graph Catalog feature on a Lord of the Rings dataset.ipynb",
      "provenance": [],
      "include_colab_link": true
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}